/*
 *                  BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 * 
 * Created on Jun 4, 2007
 * 
 */

package org.biojava.services.das.servlets;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.biojava.dasobert.das.DasTimeFormat;
import org.biojava.dasobert.das2.io.DasSourceIndexWriterImpl;
import org.biojava.dasobert.das2.io.DasSourceWriter;
import org.biojava.dasobert.das2.io.DasSourceWriterImpl;
import org.biojava.dasobert.dasregistry.DasCoordinateSystem;
import org.biojava.dasobert.dasregistry.DasSource;
import org.biojava.services.das.dao.OrganismBean;
import org.biojava.services.das.registry.DasRegistrySql;
import org.biojava.services.das2.Das1SourceDbProvider;
import org.biojava.services.das2.DasSourceProvider;
import org.biojava.utils.xml.PrettyXMLWriter;
import org.biojava.utils.xml.XMLWriter;

public class ServletResponseIndexWriter {
	DasSourceProvider das1provider;

	// public static final String XML_CONTENT_TYPE =
	// "application/x-das-sources+xml";
	
	private int numberOfDasSourceEntries;
	private int numberOfCoordinateEntries;
	private int numberOfOrganismEntries;
	private int numberOfTypesEntries;

	private String directory = "";// directory to write indexed files to

	public ServletResponseIndexWriter(String directory) {
		this.directory = directory;
	}

	private XMLWriter initSourcesResponse(PrintWriter pw) throws IOException {

		PrettyXMLWriter xw = new PrettyXMLWriter(pw);
		xw.openTag("database");
		xw.openTag("name");
		xw.print("DAS Registry");
		xw.closeTag("name");
		xw.openTag("description");
		xw
				.print("The DAS Registry holds information for Distributed Annotation System (DAS) sources from around the world");
		xw.closeTag("description");
		Date today;
		String dateOut;
		DateFormat dateFormatter;
		today = new Date();
		dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
		dateOut = dateFormatter.format(today).replaceAll("/", "-");

		xw.openTag("release");
		xw.print(dateOut);
		xw.closeTag("release");
		xw.openTag("release_date");

		xw.print(dateOut);
		xw.closeTag("release_date");
		xw.openTag("entry_count");
		xw.print(Integer.toString(this.numberOfDasSourceEntries));// currently
																	// entries
																	// =number
																	// of
																	// sources
																	// in
																	// registry
		xw.closeTag("entry_count");
		xw.openTag("entries");

		// System.out.println("XXXXX");
		// xw.openTag("SOURCES");
		// xw.attribute("xmlns",DASNS);
		// xw.attribute("xml:base","http://das.sanger.ac.uk/registry/das2/");
		return xw;

	}

	/**
	 * write the XML response needed for indexing the registry which mainly
	 * consists of the sources response for the provided DAS sources but altered
	 * @param sources
	 * @param types
	 * @param allCoordinates TODO
	 * @param resp
	 * 
	 * @throws ServletException
	 * @throws IOException
	 */
	public void writeIndexResponse(List<DasSource> sources,
			Map<String, List<Map<String, String>>> types, List<DasCoordinateSystem> allCoordinates) throws IOException {

		writeSources(sources);
		// write the coordinate systems available in the registry and then the
		// organisms already contained in the registry
		// afterwards close the tags and the response
		//das1provider = new Das1SourceDbProvider();
		//List<DasCoordinateSystem> dcs = das1provider.getCoordinateSystems();
		System.out.println("written sources");
		writeCoordinateSystemResponse(allCoordinates);
		System.out.println("written coords");
		writeTypes(types);
		System.out.println("written types");

		// can comment out organism as this is only going to change if we do an
		// update on the ncbi taxonomy database which won't be very often!!
		// OrganismBean organisms[]=das1provider.getOrganisms();
		// writeOrganismResponse(resp, organisms);

	}

	private void writeTypes(Map<String, List<Map<String, String>>> types)
			throws IOException {
		System.out.println("writing types index");
		this.numberOfTypesEntries = types.size();// size of this is the same as
													// the number of unique
													// sources with types
													// entries
		FileOutputStream fos = new FileOutputStream(directory + "DasTypes.xml");

		PrintWriter pw = new PrintWriter(fos);

		XMLWriter xw;

		xw = initTypesResponse(pw);

		// get the sources information first
		DasSourceWriter writer = new DasSourceIndexWriterImpl();

		for (String sourceIdentifier : types.keySet()) {
			// System.out.println("sourceid="+sourceIdentifier);
			List<Map<String, String>> typesInfo = types.get(sourceIdentifier);

			writer.writeDasSourceTypes(xw, sourceIdentifier, typesInfo);
		}
		closeDatabaseEntries(xw);
	}

	private XMLWriter initTypesResponse(PrintWriter pw) throws IOException {

		PrettyXMLWriter xw = new PrettyXMLWriter(pw);
		xw.openTag("database");
		xw.openTag("name");
		xw.print("DAS Registry Types");
		xw.closeTag("name");
		xw.openTag("description");
		xw
				.print("The DAS Registry holds information for Distributed Annotation System (DAS) sources from around the world this holds types from their types response");
		xw.closeTag("description");
		Date today;
		String dateOut;
		DateFormat dateFormatter;
		today = new Date();
		dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
		dateOut = dateFormatter.format(today).replaceAll("/", "-");

		xw.openTag("release");
		xw.print(dateOut);
		xw.closeTag("release");
		xw.openTag("release_date");

		xw.print(dateOut);
		xw.closeTag("release_date");
		xw.openTag("entry_count");
		xw.print(Integer.toString(this.numberOfTypesEntries));// currently
																// entries
																// =number of
																// sources in
																// registry
		xw.closeTag("entry_count");
		xw.openTag("entries");

		// System.out.println("XXXXX");
		// xw.openTag("SOURCES");
		// xw.attribute("xmlns",DASNS);
		// xw.attribute("xml:base","http://das.sanger.ac.uk/registry/das2/");
		return xw;

	}

	private void writeSources(List<DasSource> sources)
			throws FileNotFoundException, IOException {
		numberOfDasSourceEntries = sources.size();

		System.out.println("writing index response in ServletResponseWriter");
		// OutputStream s = resp.getOutputStream();
		FileOutputStream fos = new FileOutputStream(directory
				+ "DasSources.xml");

		PrintWriter pw = new PrintWriter(fos);

		XMLWriter xw;
		xw = initSourcesResponse(pw);

		// get the sources information first
		DasSourceWriter writer = new DasSourceIndexWriterImpl();

		for (int i = 0; i < numberOfDasSourceEntries; i++) {

			DasSource source = sources.get(i);
			//System.out.println(source);
			writer.writeDasSource(xw, source, false);
		}
		closeDatabaseEntries(xw);
	}

	private void closeDatabaseEntries(XMLWriter xw) throws IOException {
		xw.closeTag("entries");
		xw.closeTag("database");
		xw.close();
	}

	public void writeCoordinateSystemResponse(List<DasCoordinateSystem> dcs) {

		this.numberOfCoordinateEntries = dcs.size();
		try {

			FileOutputStream fos = new FileOutputStream(directory
					+ "DasCoordinateSystems.xml");
			PrintWriter pw = new PrintWriter(fos);

			XMLWriter xw = this.initCoordinatesResponse(pw);
			// PrintWriter pw = new PrintWriter(s);
			// PrettyXMLWriter xw = new PrettyXMLWriter(pw);
			// xw.printRaw("<?xml version='1.0' encoding='UTF-8' ?>");

			// TODO: provide a .xsl stylesheet for this response
			// xw.printRaw("<?xml-stylesheet type=\"text/xsl\" href=\"das.xsl\"?>");

			// xw.openTag("DASCOORDINATESYSTEM");
			DasSourceWriter writer = new DasSourceIndexWriterImpl();
			for (int i = 0; i < dcs.size(); i++) {
				DasCoordinateSystem coord = dcs.get(i);
				xw.openTag("entry");
				xw.attribute("id", coord.getUniqueId());
				xw.attribute("acc", coord.toString());
				xw.openTag("additional_fields");
				writer.writeCoordinateSystem(xw, coord);
				xw.closeTag("additional_fields");
				xw.closeTag("entry");
			}
			this.closeDatabaseEntries(xw);
			// xw.closeTag("DASCOORDINATESYSTEM");

			// xw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public void writeOrganismResponse(OrganismBean[] organisms) {
		// resp.setHeader("Content-Encoding","ISO-8859-1");
		// resp.setHeader("Content-Type", XML_CONTENT_TYPE);
		this.numberOfOrganismEntries = organisms.length;
		try {
			// OutputStream s = resp.getOutputStream();
			FileOutputStream fos = new FileOutputStream(directory
					+ "DasRegistryOrganisms.xml");
			PrintWriter pw = new PrintWriter(fos);
			XMLWriter xw = this.initOrganismsResponse(pw);
			// xw.printRaw("<?xml version='1.0' encoding='UTF-8' ?>");

			// TODO: provide a .xsl stylesheet for this response
			// xw.printRaw("<?xml-stylesheet type=\"text/xsl\" href=\"das.xsl\"?>");
			// System.out.println("XXXXX");

			DasSourceIndexWriterImpl writer = new DasSourceIndexWriterImpl();
			for (int i = 0; i < organisms.length; i++) {
				OrganismBean bean = organisms[i];
				if (bean.getTaxonomyId() == 0)
					continue;

				xw.openTag("entry");
				// xw.openTag("ORGANISM");
				xw.attribute("id", Integer.toString(bean.getTaxonomyId()));
				xw.openTag("additional_fields");
				writer.writeAdditionalField(xw, "uri",
						"http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?id="
								+ bean.getTaxonomyId());
				writer.writeAdditionalField(xw, "scientificName", bean
						.getScientificName());
				writer.writeAdditionalField(xw, "name", bean.getName());
				writer.writeAdditionalField(xw, "taxid", bean.getTaxonomyId()
						+ "");
				xw.closeTag("additional_fields");
				xw.closeTag("entry");

			}
			this.closeDatabaseEntries(xw);
			// xw.closeTag("ORGANISMS");

			// xw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private XMLWriter initCoordinatesResponse(PrintWriter pw)
			throws IOException {

		PrettyXMLWriter xw = new PrettyXMLWriter(pw);
		xw.openTag("database");
		xw.openTag("name");
		xw.print("DAS Registry Coordinates");
		xw.closeTag("name");
		xw.openTag("description");
		xw
				.print("DAS coordinate systems held by the DAS Registry. The DAS Registry holds information for Distributed Annotation System (DAS) sources from around the world");
		xw.closeTag("description");
		Date today;
		String dateOut;
		DateFormat dateFormatter;
		today = new Date();
		dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
		dateOut = dateFormatter.format(today).replaceAll("/", "-");

		xw.openTag("release");
		xw.print(dateOut);
		xw.closeTag("release");
		xw.openTag("release_date");

		xw.print(dateOut);
		xw.closeTag("release_date");
		xw.openTag("entry_count");
		xw.print(Integer.toString(this.numberOfCoordinateEntries));
		xw.closeTag("entry_count");
		xw.openTag("entries");

		// System.out.println("XXXXX");
		// xw.openTag("SOURCES");
		// xw.attribute("xmlns",DASNS);
		// xw.attribute("xml:base","http://das.sanger.ac.uk/registry/das2/");
		return xw;

	}

	private XMLWriter initOrganismsResponse(PrintWriter pw) throws IOException {

		PrettyXMLWriter xw = new PrettyXMLWriter(pw);
		xw.openTag("database");
		xw.openTag("name");
		xw.print("DAS Registry Organisms");
		xw.closeTag("name");
		xw.openTag("description");
		xw
				.print("Organisms currently registered with the DAS Registry. The DAS Registry holds information for Distributed Annotation System (DAS) sources from around the world");
		xw.closeTag("description");
		Date today;
		String dateOut;
		DateFormat dateFormatter;
		today = new Date();
		dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
		dateOut = dateFormatter.format(today).replaceAll("/", "-");

		xw.openTag("release");
		xw.print(dateOut);
		xw.closeTag("release");
		xw.openTag("release_date");

		xw.print(dateOut);
		xw.closeTag("release_date");
		xw.openTag("entry_count");
		xw.print(Integer.toString(this.numberOfOrganismEntries));// currently
																	// entries
																	// =number
																	// of
																	// sources
																	// in
																	// registry
		xw.closeTag("entry_count");
		xw.openTag("entries");

		// System.out.println("XXXXX");
		// xw.openTag("SOURCES");
		// xw.attribute("xmlns",DASNS);
		// xw.attribute("xml:base","http://das.sanger.ac.uk/registry/das2/");
		return xw;

	}

}
